home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / pop / dropsbr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  13.2 KB  |  693 lines

  1. /* dropsbr.c - write to a mailbox */
  2.  
  3. #include <stdio.h>
  4. #ifndef    MMDFONLY
  5. #include "../h/mh.h"
  6. #include "../h/dropsbr.h"
  7. #include "../zotnet/mts.h"
  8. #else    MMDFONLY
  9. #include "dropsbr.h"
  10. #include "strings.h"
  11. #include "mmdfonly.h"
  12. #endif    MMDFONLY
  13. #include <errno.h>
  14. #include "util.h"
  15. #include <sys/stat.h>
  16.  
  17.  
  18. #define    MMDF    1
  19. #define    UUCP    2
  20.  
  21. /*   */
  22.  
  23. static    int    mbx_style = MMDF;
  24.  
  25.  
  26. extern int  errno;
  27.  
  28.  
  29. long   lseek ();
  30.  
  31. /*   */
  32.  
  33. int     mbx_mmdf () {
  34.     int     style = mbx_style;
  35.  
  36.     mbx_style = MMDF;
  37.     return style;
  38. }
  39.  
  40.  
  41. int     mbx_uucp () {
  42.     int     style = mbx_style;
  43.  
  44.     mbx_style = UUCP;
  45.     return style;
  46. }
  47.  
  48. /*   */
  49.  
  50. int     mbx_open (file, uid, gid, mode)
  51. char   *file;
  52. int     uid,
  53.         gid,
  54.     mode;
  55. {
  56.     int     clear,
  57.             fd;
  58.  
  59.     if ((fd = mbx_Xopen (file, uid, gid, mode, &clear)) == NOTOK)
  60.     return fd;
  61.  
  62.     if (!clear)
  63.     switch (mbx_style) {
  64.         case MMDF: 
  65.         default: 
  66.         if (mbx_chk (fd) == NOTOK) {
  67.             (void) close (fd);
  68.             return NOTOK;
  69.         }
  70.         break;
  71.  
  72.         case UUCP: 
  73.         if (lseek (fd, 0L, 2) == (long) NOTOK) {
  74.             (void) close (fd);
  75.             return NOTOK;
  76.         }
  77.         break;
  78.     }
  79.  
  80.     return fd;
  81. }
  82.  
  83. /*   */
  84.  
  85. int    mbx_Xopen (file, uid, gid, mode, clear)
  86. char   *file;
  87. int    uid,
  88.     gid,
  89.     mode,
  90.        *clear;
  91. {
  92.     register int j;
  93.     int        count,
  94.             fd;
  95.     struct stat st;
  96.  
  97.     for (*clear = 0, count = 4, j = 0; count > 0; count--)
  98.     if ((fd = lkopen (file, 6)) == NOTOK)
  99.         switch (errno) {
  100.         case ENOENT: 
  101.             if (mbx_create (file, uid, gid, mode) == NOTOK)
  102.             return NOTOK;
  103.             (*clear)++;
  104.             break;
  105.  
  106. #ifdef    BSD42
  107.         case EWOULDBLOCK:
  108. #endif    BSD42
  109.         case ETXTBSY: 
  110.             j = errno;
  111.             sleep (5);
  112.             break;
  113.  
  114.         default: 
  115.             return NOTOK;
  116.         }
  117.     else {
  118.         *clear = fstat (fd, &st) != NOTOK && st.st_size == 0L;
  119.         break;
  120.     }
  121.  
  122.     errno = j;
  123.     return fd;
  124. }
  125.  
  126. /*   */
  127.  
  128. static int  mbx_create (file, uid, gid, mode)
  129. char   *file;
  130. int     uid,
  131.         gid,
  132.     mode;
  133. {
  134.     int     fd;
  135.  
  136.     if ((fd = creat (file, 0600)) == NOTOK)
  137.     return NOTOK;
  138.  
  139.     (void) close (fd);
  140.     (void) chown (file, uid, gid);
  141.     (void) chmod (file, mode);
  142.  
  143.     return OK;
  144. }
  145.  
  146.  
  147. static int  mbx_chk (fd)
  148. int     fd;
  149. {
  150.     int     count;
  151.     char    ldelim[BUFSIZ];
  152.  
  153.     count = strlen (mmdlm2);
  154.  
  155.     if (lseek (fd, (long) (-count), 2) == (long) NOTOK
  156.         || read (fd, ldelim, count) != count)
  157.     return NOTOK;
  158.     ldelim[count] = NULL;
  159.  
  160.     if (strcmp (ldelim, mmdlm2)
  161.         && write (fd, "\n", 1) != 1
  162.         && write (fd, mmdlm2, count) != count)
  163.     return NOTOK;
  164.  
  165.     return OK;
  166. }
  167.  
  168. /*   */
  169.  
  170. int    mbx_read (fp, pos, drops, noisy)
  171. register FILE  *fp;
  172. register long    pos;
  173. struct drop **drops;
  174. int    noisy;
  175. {
  176.     register int    len,
  177.                     size;
  178.     long    ld1,
  179.             ld2;
  180.     register char  *bp;
  181.     char    buffer[BUFSIZ];
  182.     register struct drop   *cp,
  183.                            *dp,
  184.                            *ep,
  185.                            *pp;
  186.  
  187.     pp = (struct drop  *) calloc ((unsigned) (len = MAXFOLDER), sizeof *dp);
  188.     if (pp == NULL) {
  189.     if (noisy)
  190.         admonish (NULLCP, "unable to allocate drop storage");
  191.     return NOTOK;
  192.     }
  193.  
  194.     ld1 = (long) strlen (mmdlm1);
  195.     ld2 = (long) strlen (mmdlm2);
  196.  
  197.     (void) fseek (fp, pos, 0);
  198.     for (ep = (dp = pp) + len - 1; fgets (buffer, sizeof buffer, fp);) {
  199.     size = 0;
  200.     if (strcmp (buffer, mmdlm1) == 0)
  201.         pos += ld1, dp -> d_start = pos;
  202.     else {
  203.         dp -> d_start = pos, pos += (long) strlen (buffer);
  204.         for (bp = buffer; *bp; bp++, size++)
  205.         if (*bp == '\n')
  206.             size++;
  207.     }
  208.  
  209.     while (fgets (buffer, sizeof buffer, fp) != NULL)
  210.         if (strcmp (buffer, mmdlm2) == 0)
  211.         break;
  212.         else {
  213.         pos += (long) strlen (buffer);
  214.         for (bp = buffer; *bp; bp++, size++)
  215.             if (*bp == '\n')
  216.             size++;
  217.         }
  218.  
  219.     if (dp -> d_start != pos) {
  220.         dp -> d_id = 0;
  221.         dp -> d_size = size;
  222.         dp -> d_stop = pos;
  223.         dp++;
  224.     }
  225.     pos += ld2;
  226.  
  227.     if (dp >= ep) {
  228.         register int    curlen = dp - pp;
  229.  
  230.         cp = (struct drop  *) realloc ((char *) pp,
  231.                             (unsigned) (len += MAXFOLDER) * sizeof *pp);
  232.         if (cp == NULL) {
  233.         if (noisy)
  234.             admonish (NULLCP, "unable to allocate drop storage");
  235.         free ((char *) pp);
  236.         return 0;
  237.         }
  238.         dp = cp + curlen, ep = (pp = cp) + len - 1;
  239.     }
  240.     }
  241.  
  242.     if (dp == pp)
  243.     free ((char *) pp);
  244.     else
  245.     *drops = pp;
  246.     return (dp - pp);
  247. }
  248.  
  249. /*   */
  250.  
  251. int    mbx_write (mailbox, md, fp, id, pos, stop, mapping, noisy)
  252. char   *mailbox;
  253. register FILE *fp;
  254. int     md,
  255.     id,
  256.     mapping,
  257.     noisy;
  258. register long    pos,
  259.         stop;
  260. {
  261.     register int    i,
  262.                     j,
  263.                     size;
  264.     register long   start,
  265.                     off;
  266.     register char  *cp;
  267.     char    buffer[BUFSIZ];
  268.  
  269.     off = lseek (md, 0L, 1);
  270.     j = strlen (mmdlm1);
  271.     if (write (md, mmdlm1, j) != j)
  272.     return NOTOK;
  273.     start = lseek (md, 0L, 1);
  274.     size = 0;
  275.  
  276.     (void) fseek (fp, pos, 0);
  277.     while (fgets (buffer, sizeof buffer, fp) != NULL && pos < stop) {
  278.     i = strlen (buffer);
  279.     for (j = 0; (j = stringdex (mmdlm1, buffer)) >= 0; buffer[j]++)
  280.         continue;
  281.     for (j = 0; (j = stringdex (mmdlm2, buffer)) >= 0; buffer[j]++)
  282.         continue;
  283.     if (write (md, buffer, i) != i)
  284.         return NOTOK;
  285.     pos += (long) i;
  286.     if (mapping)
  287.         for (cp = buffer; i-- > 0; size++)
  288.         if (*cp++ == '\n')
  289.             size++;
  290.     }
  291.  
  292.     stop = lseek (md, 0L, 1);
  293.     j = strlen (mmdlm2);
  294.     if (write (md, mmdlm2, j) != j)
  295.     return NOTOK;
  296.     if (mapping)
  297.     (void) map_write (mailbox, md, id, start, stop, off, size, noisy);
  298.  
  299.     return OK;
  300. }
  301.  
  302. /*   */
  303.  
  304. int     mbx_copy (mailbox, md, fd, mapping, text, noisy)
  305. char   *mailbox;
  306. int     md,
  307.         fd,
  308.     mapping,
  309.     noisy;
  310. char   *text;
  311. {
  312.     register int    i,
  313.                     j,
  314.                     size;
  315.     register long   start,
  316.                     stop,
  317.                     pos;
  318.     register char  *cp;
  319.     char    buffer[BUFSIZ];
  320.     register FILE  *fp;
  321.  
  322.     pos = lseek (md, 0L, 1);
  323.     size = 0;
  324.  
  325.     switch (mbx_style) {
  326.     case MMDF: 
  327.     default: 
  328.         j = strlen (mmdlm1);
  329.         if (write (md, mmdlm1, j) != j)
  330.         return NOTOK;
  331.         start = lseek (md, 0L, 1);
  332.  
  333.         if (text) {
  334.         i = strlen (text);
  335.         if (write (md, text, i) != i)
  336.             return NOTOK;
  337.         for (cp = text; *cp++; size++)
  338.             if (*cp == '\n')
  339.             size++;
  340.         }
  341.             
  342.         while ((i = read (fd, buffer, sizeof buffer)) > 0) {
  343.         for (j = 0;
  344.             (j = stringdex (mmdlm1, buffer)) >= 0;
  345.             buffer[j]++)
  346.             continue;
  347.         for (j = 0;
  348.             (j = stringdex (mmdlm2, buffer)) >= 0;
  349.             buffer[j]++)
  350.             continue;
  351.         if (write (md, buffer, i) != i)
  352.             return NOTOK;
  353.         if (mapping)
  354.             for (cp = buffer; i-- > 0; size++)
  355.             if (*cp++ == '\n')
  356.                 size++;
  357.         }
  358.  
  359.         stop = lseek (md, 0L, 1);
  360.         j = strlen (mmdlm2);
  361.         if (write (md, mmdlm2, j) != j)
  362.         return NOTOK;
  363.         if (mapping)
  364.         (void) map_write (mailbox, md, 0, start, stop, pos, size, noisy);
  365.  
  366.         return (i != NOTOK ? OK : NOTOK);
  367.  
  368.     case UUCP:         /* I hate this... */
  369.         if ((j = dup (fd)) == NOTOK)
  370.         return NOTOK;
  371.         if ((fp = fdopen (j, "r")) == NULL) {
  372.         (void) close (j);
  373.         return NOTOK;
  374.         }
  375.         start = lseek (md, 0L, 1);
  376.  
  377.         if (text) {
  378.         i = strlen (text);
  379.         if (write (md, text, i) != i)
  380.             return NOTOK;
  381.         for (cp = buffer; *cp++; size++)
  382.             if (*cp == '\n')
  383.             size++;
  384.         }
  385.             
  386.         for (j = 0; fgets (buffer, sizeof buffer, fp) != NULL; j++) {
  387.         if (j != 0 && strncmp (buffer, "From ", 5) == 0) {
  388.             (void) write (fd, ">", 1);
  389.             size++;
  390.         }
  391.         i = strlen (buffer);
  392.         if (write (md, buffer, i) != i) {
  393.             (void) fclose (fp);
  394.             return NOTOK;
  395.         }
  396.         if (mapping)
  397.             for (cp = buffer; i-- > 0; size++)
  398.             if (*cp++ == '\n')
  399.                 size++;
  400.         }
  401.  
  402.         (void) fclose (fp);
  403.         (void) lseek (fd, 0L, 2);
  404.         stop = lseek (md, 0L, 1);
  405.         if (mapping)
  406.         (void) map_write (mailbox, md, 0, start, stop, pos, size,
  407.                 noisy);
  408.  
  409.         return OK;
  410.     }
  411. }
  412.  
  413. /*   */
  414.  
  415. int    mbx_size (md, start, stop)
  416. int    md;
  417. long    start,
  418.     stop;
  419. {
  420.     register int    i,
  421.                     fd;
  422.     register long   pos;
  423.     register FILE  *fp;
  424.  
  425.     if ((fd = dup (md)) == NOTOK || (fp = fdopen (fd, "r")) == NULL) {
  426.     if (fd != NOTOK)
  427.         (void) close (fd);
  428.     return NOTOK;
  429.     }
  430.  
  431.     (void) fseek (fp, start, 0);
  432.     for (i = 0, pos = stop - start; pos-- > 0; i++)
  433.     if (fgetc (fp) == '\n')
  434.         i++;
  435.  
  436.     (void) fclose (fp);
  437.  
  438.     return i;
  439. }
  440.  
  441. /*   */
  442.  
  443. int     mbx_close (mailbox, md)
  444. char   *mailbox;
  445. int     md;
  446. {
  447.     (void) lkclose (md, mailbox);
  448.  
  449.     return OK;
  450. }
  451.  
  452. /*   */
  453.  
  454. /* This function is performed implicitly by getbbent.c:
  455.  
  456.         bb -> bb_map = map_name (bb -> bb_file);
  457. */
  458.  
  459. char    *map_name (file)
  460. register char    *file;
  461. {
  462.     register char  *cp,
  463.                    *dp;
  464.     static char buffer[BUFSIZ];
  465.  
  466.     if ((dp = index (cp = r1bindex (file, '/'), '.')) == NULL)
  467.     dp = cp + strlen (cp);
  468.     if (cp == file)
  469.     (void) sprintf (buffer, ".%.*s%s", dp - cp, cp, ".map");
  470.     else
  471.     (void) sprintf (buffer, "%.*s.%.*s%s", cp - file, file, dp - cp,
  472.         cp, ".map");
  473.  
  474.     return buffer;
  475. }
  476.  
  477. /*   */
  478.  
  479. int    map_read (file, pos, drops, noisy)
  480. char   *file;
  481. long    pos;
  482. struct drop **drops;
  483. int    noisy;
  484. {
  485.     register int    i,
  486.                     md,
  487.                     msgp;
  488.     register char  *cp;
  489.     struct drop d;
  490.     register struct drop   *mp,
  491.                            *dp;
  492.  
  493.     if ((md = open (cp = map_name (file), 0)) == NOTOK
  494.         || map_chk (cp, md, mp = &d, pos, noisy)) {
  495.     if (md != NOTOK)
  496.         (void) close (md);
  497.     return 0;
  498.     }
  499.  
  500.     msgp = mp -> d_id;
  501.     dp = (struct drop  *) calloc ((unsigned) msgp, sizeof *dp);
  502.     if (dp == NULL) {
  503.     (void) close (md);
  504.     return 0;
  505.     }
  506.  
  507.     (void) lseek (md, (long) sizeof *mp, 0);
  508.     if ((i = read (md, (char *) dp, msgp * sizeof *dp)) < sizeof *dp) {
  509.     i = 0;
  510.     free ((char *) dp);
  511.     }
  512.     else
  513.     *drops = dp;
  514.  
  515.     (void) close (md);
  516.  
  517.     return (i / sizeof *dp);
  518. }
  519.  
  520. /*   */
  521.  
  522. int     map_write (mailbox, md, id, start, stop, pos, size, noisy)
  523. register char   *mailbox;
  524. int     md,
  525.         id,
  526.     size,
  527.     noisy;
  528. long    start,
  529.         stop,
  530.         pos;
  531. {
  532.     register int    i;
  533.     int     clear,
  534.             fd,
  535.             td;
  536.     char   *file;
  537.     register struct drop   *dp;
  538.     struct drop    d1,
  539.            d2,
  540.                   *rp;
  541.     register FILE *fp;
  542.  
  543.     if ((fd = map_open (file = map_name (mailbox), &clear, md)) == NOTOK)
  544.     return NOTOK;
  545.  
  546.     if (!clear && map_chk (file, fd, &d1, pos, noisy)) {
  547.     (void) unlink (file);
  548.     (void) mbx_close (file, fd);
  549.     if ((fd = map_open (file, &clear, md)) == NOTOK)
  550.         return NOTOK;
  551.     clear++;
  552.     }
  553.  
  554.     if (clear) {
  555.     if ((td = dup (md)) == NOTOK || (fp = fdopen (td, "r")) == NULL) {
  556.         if (noisy)
  557.         admonish (file, "unable to %s", td != NOTOK ? "fdopen" : "dup");
  558.         if (td != NOTOK)
  559.         (void) close (td);
  560.         (void) mbx_close (file, fd);
  561.         return NOTOK;
  562.     }
  563.  
  564.     switch (i = mbx_read (fp, 0L, &rp, noisy)) {
  565.         case NOTOK:
  566.         (void) fclose (fp);
  567.         (void) mbx_close (file, fd);
  568.         return NOTOK;
  569.  
  570.         case OK:
  571.         break;
  572.  
  573.         default:
  574.         d1.d_id = 0;
  575.         for (dp = rp; i-- >0; dp++) {
  576.             if (dp -> d_start == start)
  577.             dp -> d_id = id;
  578.             (void) lseek (fd, (long) (++d1.d_id * sizeof *dp), 0);
  579.             if (write (fd, (char *) dp, sizeof *dp) != sizeof *dp) {
  580.             if (noisy)
  581.                 admonish (file, "write error");
  582.             (void) mbx_close (file, fd);
  583.             (void) fclose (fp);
  584.             return NOTOK;
  585.             }
  586.         }
  587.         free ((char *) rp);
  588.         break;
  589.     }
  590.     }
  591.     else {
  592.     dp = &d2;
  593.     dp -> d_id = id;
  594.     dp -> d_size = size ? size : mbx_size (fd, start, stop);
  595.     dp -> d_start = start;
  596.     dp -> d_stop = stop;
  597.     (void) lseek (fd, (long) (++d1.d_id * sizeof *dp), 0);
  598.     if (write (fd, (char *) dp, sizeof *dp) != sizeof *dp) {
  599.         if (noisy)
  600.         admonish (file, "write error");
  601.         (void) mbx_close (file, fd);
  602.         return NOTOK;
  603.     }
  604.     }
  605.  
  606.     dp = &d1;
  607.     dp -> d_size = DRVRSN;
  608.     dp -> d_start = DRMAGIC;
  609.     dp -> d_stop = lseek (md, 0L, 1);
  610.     (void) lseek (fd, 0L, 0);
  611.     if (write (fd, (char *) dp, sizeof *dp) != sizeof *dp) {
  612.     if (noisy)
  613.         admonish (file, "write error");
  614.     (void) mbx_close (file, fd);
  615.     return NOTOK;
  616.     }
  617.  
  618.     (void) mbx_close (file, fd);
  619.  
  620.     return OK;
  621. }
  622.  
  623. /*   */
  624.  
  625. static int  map_open (file, clear, md)
  626. char   *file;
  627. int    *clear,
  628.     md;
  629. {
  630.     int        mode;
  631.     struct  stat st;
  632.  
  633.     mode = fstat (md, &st) != NOTOK ? (int) (st.st_mode & 0777) : m_gmprot ();
  634.     return mbx_Xopen (file, st.st_uid, st.st_gid, mode, clear);
  635. }
  636.  
  637. /*   */
  638.  
  639. int  map_chk (file, fd, dp, pos, noisy)
  640. char   *file;
  641. int     fd,
  642.     noisy;
  643. register struct drop *dp;
  644. long    pos;
  645. {
  646.     long    count;
  647.     struct drop d;
  648.     register struct drop    *dl;
  649.  
  650.     if (read (fd, (char *) dp, sizeof *dp) != sizeof *dp) {
  651. #ifdef    notdef
  652.     admonish (NULLCP, "%s: missing or partial index", file);
  653. #endif    notdef
  654.     return NOTOK;
  655.     }
  656.     if (dp -> d_size != DRVRSN) {
  657.     if (noisy)
  658.         admonish (NULLCP, "%s: version mismatch", file);
  659.     return NOTOK;
  660.     }
  661.     if (dp -> d_start != DRMAGIC) {
  662.     if (noisy)
  663.         admonish (NULLCP, "%s: bad magic number", file);
  664.     return NOTOK;
  665.     }
  666.     if (dp -> d_stop != pos) {
  667.     if (noisy && pos != 0L)
  668.         admonish (NULLCP,
  669.             "%s: pointer mismatch or incomplete index (%ld!=%ld)", 
  670.             file, dp -> d_stop, pos);
  671.     return NOTOK;
  672.     }
  673.  
  674.     if ((long) ((dp -> d_id + 1) * sizeof *dp) != lseek (fd, 0L, 2)) {
  675.     if (noisy)
  676.         admonish (NULLCP, "%s: corrupt index(1)", file);
  677.     return NOTOK;
  678.     }
  679.  
  680.     dl = &d;
  681.     count = (long) strlen (mmdlm2);
  682.     (void) lseek (fd, (long) (dp -> d_id * sizeof *dp), 0);
  683.     if (read (fd, (char *) dl, sizeof *dl) != sizeof *dl
  684.         || (dl -> d_stop != dp -> d_stop
  685.         && dl -> d_stop + count != dp -> d_stop)) {
  686.     if (noisy)
  687.         admonish (NULLCP, "%s: corrupt index(2)", file);
  688.     return NOTOK;
  689.     }
  690.  
  691.     return OK;
  692. }
  693.